package fi.jamk.ourcookingapp.activity;

import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ExecutionException;

import org.json.JSONException;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.text.SpannableString;
import android.text.style.UnderlineSpan;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.view.ViewGroup.LayoutParams;
import android.view.inputmethod.EditorInfo;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import android.widget.Spinner;
import android.widget.TableRow;
import android.widget.TextView;
import android.widget.Toast;
import fi.jamk.ourcookingapp.R;
import fi.jamk.ourcookingapp.backend.MyTools;
import fi.jamk.ourcookingapp.backend.architecture.manager.ReceiptManager;
import fi.jamk.ourcookingapp.backend.architecture.services.DownloadImageService;
import fi.jamk.ourcookingapp.backend.exceptions.EmptyInputException;
import fi.jamk.ourcookingapp.backend.exceptions.EmptySearchException;
import fi.jamk.ourcookingapp.backend.exceptions.NoRatingException;
import fi.jamk.ourcookingapp.backend.exceptions.NoReceiptException;
import fi.jamk.ourcookingapp.backend.exceptions.NoUserException;
import fi.jamk.ourcookingapp.backend.model.Comment;
import fi.jamk.ourcookingapp.backend.model.Ingredient;
import fi.jamk.ourcookingapp.backend.model.Rating;
import fi.jamk.ourcookingapp.backend.model.Receipt;
import fi.jamk.ourcookingapp.backend.model.Step;

/**
 * Activity for showing details of receipt.
 * User can add comments and rate the recept.
 * @author Marius
 */
public class ReceiptDetailActivity extends Activity {

	private static final String REMOVE_FAVOURITE = "remove favourite";

	public static final String ARG_ITEM = "receipt";

	public static final String SOURCE = "source";

	public static final String STREAM = "stream";
	public static final String FAVOURITES = "favourites";

	private static final int WIDHT_COMMENT = 350;

	private static final int WIDTH_STEP = 300;

	private Intent intent;
	
	private Receipt receipt;

	private DateFormat dateFormat;
	
	private Rating rating;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.detail_receipt);
		getActionBar().setDisplayHomeAsUpEnabled(true);
		dateFormat = android.text.format.DateFormat.getDateFormat(getApplicationContext());
		try {
			initVariables();
		} catch (NoReceiptException | InterruptedException | ExecutionException | JSONException e) {
			Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_SHORT).show();
		}
		initContent();
		initRating();
	}
	
	/**
	 * Initialize functionality for rating
	 */
	private void initRating(){
		final Button rate = (Button) findViewById(R.id.btnRating);
		rate.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				try {
					receipt.setRating(AppActivity.facade.rateReceipt(receipt, rating));
					rate.setEnabled(false);
					// update ratint stars
					initStars();
				} catch (NoReceiptException | NoRatingException | InterruptedException | ExecutionException | NumberFormatException | JSONException e) {
					Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_SHORT).show();
				}
			}
		});
		
		
		final Spinner spnRating = (Spinner) findViewById(R.id.spnRating);
		List<String> ratingList = new ArrayList<String>();
		for (int i = 0; i <= 10; i++) {
			ratingList.add("" + ((double)i/2));
		}
		ArrayAdapter<String> dataAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_dropdown_item, ratingList);
		spnRating.setAdapter(dataAdapter);
		
		spnRating.post(new Runnable() {
		    public void run() {
		    	spnRating.setOnItemSelectedListener(new OnItemSelectedListener() {
					@Override
					public void onItemSelected(AdapterView<?> parent, View view,
							int pos, long id) {
						//Toast.makeText(parent.getContext(), parent.getItemAtPosition(pos).toString(), Toast.LENGTH_LONG).show();
						rate.setEnabled(true);
						rating = new Rating();
						rating.setAmount(Double.parseDouble(parent.getItemAtPosition(pos).toString()));
						rating.setRecipt(receipt);
						rating.setUser(AppActivity.facade.getCurrentUser());
					}

					@Override
					public void onNothingSelected(AdapterView<?> parent) {
					}
					
				});
		    }
		});

	}
	
	/**
	 * Initialize the receipt's content
	 */
	private void initContent() {
		// receipt image
		ImageView receiptImage = (ImageView) findViewById(R.id.receiptImage);
		new DownloadImageService(receiptImage).execute(receipt.getID() + ".png");
		
		// receipt duration
		TextView txtDuration = (TextView) findViewById(R.id.receiptDuration);
		int hour = receipt.getDuration() / 60;
		int minutes = receipt.getDuration() - hour * 60;
		txtDuration.setText(hour + "h " + minutes + "m");

		// receipt effort
		TextView txtEffort = (TextView) findViewById(R.id.receiptEffort);
		txtEffort.setText(receipt.getEffort());
		
		// receipt date
		TextView txtDate = (TextView) findViewById(R.id.receiptDate);
		txtDate.setText(dateFormat.format(receipt.getDate()));
		
		// receipt clicks
		TextView txtClicks = (TextView) findViewById(R.id.receiptClicks);
		txtClicks.setText(receipt.getCountClicks() + "");
		
		// receipt username
		TextView txtUsername = (TextView) findViewById(R.id.receiptUsername);
		SpannableString content = new SpannableString(receipt.getUser().getLoginName());
		content.setSpan(new UnderlineSpan(), 0, content.length(), 0);
		txtUsername.setText(content);
		txtUsername.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				String message = receipt.getUser().getLoginName() + " " + getResources().getString(R.string.addedUserFriendList);
				try {
					AppActivity.facade.addToFriendList(AppActivity.facade.getCurrentUser(), receipt.getUser());
				} catch (EmptyInputException | NoUserException | InterruptedException | ExecutionException | JSONException e) {
					message = e.getMessage();
				}
				Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show();
			}
		});
		
		// receipt count
		TextView txtCountReceipts = (TextView) findViewById(R.id.receiptCount);
		try {
			AppActivity.facade.setFilter(ReceiptManager.USER_ID, receipt.getUser().getID());
			txtCountReceipts.setText(AppActivity.facade.filter(true).size() + "");
		} catch (EmptySearchException | InterruptedException | ExecutionException | JSONException | NoReceiptException e) {
			txtCountReceipts.setText(1 + "");
		}
		
		// receipt name
		TextView txtReceiptName = (TextView) findViewById(R.id.receiptName);
		txtReceiptName.setText(receipt.getName());
		
		// rating stars
		initStars();
		
		// receipt description
		TextView txtDescription = (TextView) findViewById(R.id.receiptDescription);
		txtDescription.setText(receipt.getDescription());
		
		final Button btnAddToFavourite = (Button) findViewById(R.id.addToFavourite);
		btnAddToFavourite.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				try {
					if(btnAddToFavourite.getText().equals(REMOVE_FAVOURITE)){
						AppActivity.facade.removeFromFavourite(receipt, AppActivity.facade.getCurrentUser());
						btnAddToFavourite.setText("add favourite");
					} else {
						AppActivity.facade.addToFavourite(receipt, AppActivity.facade.getCurrentUser());
						btnAddToFavourite.setText(REMOVE_FAVOURITE);
					}
				} catch (NoReceiptException | JSONException | InterruptedException | ExecutionException e) {
					e.printStackTrace();
				}
			}
		});
		
		try {
			for (Receipt rec : AppActivity.facade.getFavourites()) {
				if(rec.getID() == receipt.getID()){
					btnAddToFavourite.setText(REMOVE_FAVOURITE);
					break;
				}
			}
		} catch (JSONException | InterruptedException | ExecutionException e1) {
		}
		
		final EditText txtComment = (EditText) findViewById(R.id.txtCommentText);
		txtComment.setOnTouchListener(new OnTouchListener() {
			@SuppressLint("ClickableViewAccessibility")
			@Override
			public boolean onTouch(View v, MotionEvent event) {
				v.setFocusable(true);
	            v.setFocusableInTouchMode(true);
				return false;
			}
		});
		Button btnAddComment = (Button) findViewById(R.id.btnAddComment);
		btnAddComment.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				String string = txtComment.getText().toString();
				if(!MyTools.isEmpty(string)){
					Comment comment = new Comment(string, new Date(), AppActivity.facade.getCurrentUser());
					comment.setReciept(receipt);
					try {
						AppActivity.facade.createComment(comment);
						receipt.getLstComment().add(comment);
						showComments();
						txtComment.setText("");
					} catch (EmptyInputException | InterruptedException | ExecutionException | JSONException e) {
						e.printStackTrace();
					}
				} else {
					Toast.makeText(getApplicationContext(), getResources().getString(R.string.emptyComment), Toast.LENGTH_SHORT).show();
				}
			}
		});
		
		showIngredients();
		showSteps();
		showComments();
	}

	private void initStars() {
		int[] stars = {R.id.star1, R.id.star2, R.id.star3, R.id.star4, R.id.star5};
		for (int i = 0; i < stars.length; i++) {
			ImageView star = (ImageView) findViewById(stars[i]);
			star.setImageResource(R.drawable.null_star);
		}
		int starsCount = (int)receipt.getRating();
		for (int i = 1; i <= starsCount; i++) {
			ImageView star = (ImageView) findViewById(stars[i - 1]);
			star.setImageResource(R.drawable.full_star);
		}
		// if the rating has 0.5 left
		if(receipt.getRating() > 0 && receipt.getRating() % starsCount != 0){
			ImageView star = (ImageView) findViewById(stars[starsCount]);
			star.setImageResource(R.drawable.half_star);
		}
	}
	
	/**
	 * Creating the view for the comments.
	 */
	private void showComments() {
		TableRow container = (TableRow) findViewById(R.id.comments);
		container.removeAllViews();
		
		ScrollView sv = new ScrollView(this);
		LinearLayout ll = new LinearLayout(this);
		ll.setOrientation(LinearLayout.VERTICAL);
		
		for (Comment com : this.receipt.getLstComment()) {
			LinearLayout lContent = new LinearLayout(this);
			lContent.setOrientation(LinearLayout.VERTICAL);
			
			TextView txtUserName = new TextView(this);
			txtUserName.setText(com.getUser().getLoginName() + "(" + dateFormat.format(com.getDate()) +")");
			lContent.addView(txtUserName);
			
			TextView txtComment = new TextView(this);
			txtComment.setText(com.getText());
			txtComment.setSingleLine(false);
			txtComment.setImeOptions(EditorInfo.IME_FLAG_NO_ENTER_ACTION);
			txtComment.setMaxWidth(dpToPx(WIDHT_COMMENT));
			txtComment.setMinWidth(dpToPx(WIDHT_COMMENT));
			lContent.addView(txtComment);
			
			ll.addView(lContent);
		}
		sv.addView(ll);
		container.addView(sv);
	}

	/**
	 * Initialize the functionality for the steps
	 */
	protected void showSteps() {
		TableRow container = (TableRow) findViewById(R.id.steps);
		container.removeAllViews();
		
		ScrollView sv = new ScrollView(this);
		LinearLayout ll = new LinearLayout(this);
		ll.setOrientation(LinearLayout.VERTICAL);
		
		for (Step step : this.receipt.getLstStep()) {
			LinearLayout lContent = new LinearLayout(this);
			lContent.setOrientation(LinearLayout.HORIZONTAL);
			
			TextView txtStepNr = new TextView(this);
			txtStepNr.setText("Step " + step.getNumber() + ": ");
			lContent.addView(txtStepNr);
			
			TextView txtStep = new TextView(this);
			txtStep.setText(step.getDescription());
			txtStep.setSingleLine(false);
			txtStep.setImeOptions(EditorInfo.IME_FLAG_NO_ENTER_ACTION);
			txtStep.setMinWidth(dpToPx(WIDTH_STEP));
			txtStep.setMaxWidth(dpToPx(WIDTH_STEP));
			lContent.addView(txtStep);
			
			ll.addView(lContent);
		}
		sv.addView(ll);
		container.addView(sv);
	}

	/**
	 * Initialize the functionality for the ingredients
	 */
	protected void showIngredients(){
		TableRow container = (TableRow) findViewById(R.id.ingredients);
		container.removeAllViews();
		
		ScrollView sv = new ScrollView(this);
		LinearLayout ll = new LinearLayout(this);
		ll.setOrientation(LinearLayout.VERTICAL);
		
		LayoutParams params = new LayoutParams(300, 50);
		
		for (Ingredient ing : receipt.getLstIngredient()) {
			LinearLayout lContent = new LinearLayout(this);
			lContent.setOrientation(LinearLayout.HORIZONTAL);
			
			TextView txtIngName = new TextView(this);
			txtIngName.setText(ing.getName());
			txtIngName.setLayoutParams(params);
			lContent.addView(txtIngName);
			
			TextView txtIngAmount = new TextView(this);
			txtIngAmount.setText(ing.getAmount()+"");
			txtIngAmount.setLayoutParams(params);
			lContent.addView(txtIngAmount);
			
			TextView txtIngType = new TextView(this);
			txtIngType.setText(ing.getTypeOfAmount());
			lContent.addView(txtIngType);
			
			ll.addView(lContent);
		}
		
		sv.addView(ll);
		container.addView(sv);
	}

	/**
	 * Checking which destination for going back
	 * @throws NoReceiptException
	 * @throws InterruptedException
	 * @throws ExecutionException
	 * @throws JSONException
	 */
	private void initVariables() throws NoReceiptException, InterruptedException, ExecutionException, JSONException {
		receipt = (Receipt) getIntent().getSerializableExtra(ARG_ITEM);
		receipt.setLstIngredient(AppActivity.facade.ingredientsByReceipt(receipt));
		receipt.setLstStep(AppActivity.facade.stepsByReceipt(receipt));
		receipt.setLstComment(AppActivity.facade.commentsByReceipt(receipt));
		switch (getIntent().getStringExtra(SOURCE)) {
		case STREAM:
			intent = new Intent(this, StreamActivity.class);	
			break;
		case FAVOURITES:
			intent = new Intent(this, FavouritesActivity.class);	
			break;
		default:
			break;
		}
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		int id = item.getItemId();
		if (id == android.R.id.home) {
			navigateUpTo(intent);
			return true;
		}
		return super.onOptionsItemSelected(item);
	}
	
	
	private int dpToPx(int dp){
	    float density = getApplicationContext().getResources().getDisplayMetrics().density;
	    return Math.round((float)dp * density);
	}
}
